import { expect } from 'chai'

import * as error from '../../src/utils/error.js'
import * as symbol from '../../src/utils/symbol.js'

describe('Utils => Symbol', () => {
  it('ADD', () => {
    expect(symbol.ADD(10, 4)).to.equal(14)
    expect(symbol.ADD(1.2, 4)).to.equal(5.2)
    expect(symbol.ADD(1, 'string')).to.equal(error.value)

    expect(symbol.ADD()).to.equal(error.na)
    expect(symbol.ADD(undefined, undefined)).to.equal(0)
    expect(symbol.ADD(1, undefined)).to.equal(1)
    expect(symbol.ADD(undefined, 1)).to.equal(1)
    expect(symbol.ADD(null, undefined)).to.equal(0)
    expect(symbol.ADD(undefined, null)).to.equal(0)
    expect(symbol.ADD(null, null)).to.equal(0)
    expect(symbol.ADD(null, 1)).to.equal(1)
    expect(symbol.ADD(error.na, undefined)).to.equal(error.na)
    expect(symbol.ADD(error.na, null)).to.equal(error.na)
    expect(symbol.ADD(error.na, 1)).to.equal(error.na)
    expect(symbol.ADD(true, false)).to.equal(1)
  })

  it('DIVIDE', () => {
    expect(symbol.DIVIDE(10, 4)).to.equal(2.5)
    expect(symbol.DIVIDE(12, -6)).to.equal(-2)
    expect(symbol.DIVIDE(0, 0)).to.equal(error.div0)
    expect(symbol.DIVIDE(1, 0)).to.equal(error.div0)
    expect(symbol.DIVIDE(0, 1)).to.equal(0)
    expect(symbol.DIVIDE(1, 'string')).to.equal(error.value)

    expect(symbol.DIVIDE()).to.equal(error.na)
    expect(symbol.DIVIDE(undefined, undefined)).to.equal(error.div0)
    expect(symbol.DIVIDE(1, undefined)).to.equal(error.div0)
    expect(symbol.DIVIDE(undefined, 1)).to.equal(0)
    expect(symbol.DIVIDE(null, undefined)).to.equal(error.div0)
    expect(symbol.DIVIDE(undefined, null)).to.equal(error.div0)
    expect(symbol.DIVIDE(null, null)).to.equal(error.div0)
    expect(symbol.DIVIDE(null, 1)).to.equal(0)
    expect(symbol.DIVIDE(error.na, undefined)).to.equal(error.na)
    expect(symbol.DIVIDE(error.na, null)).to.equal(error.na)
    expect(symbol.DIVIDE(error.na, 1)).to.equal(error.na)
    expect(symbol.DIVIDE(false, true)).to.equal(0)
  })

  it('EQ', () => {
    expect(symbol.EQ(10, 10)).to.equal(true)
    expect(symbol.EQ(1.2, 1.2)).to.equal(true)
    expect(symbol.EQ('hello', 'jim')).to.equal(false)
    expect(symbol.EQ('hello', 'hello')).to.equal(true)
    expect(symbol.EQ(123, 'hello')).to.equal(false)
    expect(symbol.EQ(true, true)).to.equal(true)
    expect(symbol.EQ(false, false)).to.equal(true)
    expect(symbol.EQ(false, 0)).to.equal(false)

    expect(symbol.EQ()).to.equal(error.na)
    expect(symbol.EQ(undefined, undefined)).to.equal(true)
    expect(symbol.EQ(null, null)).to.equal(true)
    expect(symbol.EQ(undefined, null)).to.equal(true)
    expect(symbol.EQ(error.na)).to.equal(error.na)
    expect(symbol.EQ(1, undefined)).to.equal(false)
    expect(symbol.EQ(1, 'string')).to.equal(false)
  })

  it('GT', () => {
    expect(symbol.GT(10, 4)).to.equal(true)
    expect(symbol.GT(10, 10)).to.equal(false)
    expect(symbol.GT(10, 12)).to.equal(false)
    expect(symbol.GT()).to.equal(error.na)
    expect(symbol.GT(undefined, undefined)).to.equal(false)
    expect(symbol.GT(1, undefined)).to.equal(true)
    expect(symbol.GT(0, undefined)).to.equal(false)
    expect(symbol.GT(-1, undefined)).to.equal(false)
    expect(symbol.GT(error.na)).to.equal(error.na)
    expect(symbol.GT(1, 'string')).to.equal(false)
    expect(symbol.GT('string', 2)).to.equal(true)
    expect(symbol.GT('a', 'a')).to.equal(false)
    expect(symbol.GT('a', 'ab')).to.equal(false)
    expect(symbol.GT('ab', 'a')).to.equal(true)
  })

  it('GTE', () => {
    expect(symbol.GTE(10, 4)).to.equal(true)
    expect(symbol.GTE(10, 10)).to.equal(true)
    expect(symbol.GTE(10, 12)).to.equal(false)
    expect(symbol.GTE()).to.equal(error.na)
    expect(symbol.GTE(undefined, undefined)).to.equal(true)
    expect(symbol.GTE(1, undefined)).to.equal(true)
    expect(symbol.GTE(0, undefined)).to.equal(true)
    expect(symbol.GTE(-1, undefined)).to.equal(false)
    expect(symbol.GTE(error.na)).to.equal(error.na)
    expect(symbol.GTE(1, 'string')).to.equal(false)
    expect(symbol.GTE('string', 2)).to.equal(true)
    expect(symbol.GTE('a', 'a')).to.equal(true)
    expect(symbol.GTE('a', 'ab')).to.equal(false)
    expect(symbol.GTE('ab', 'a')).to.equal(true)
  })

  it('LT', () => {
    expect(symbol.LT(10, 4)).to.equal(false)
    expect(symbol.LT(10, 10)).to.equal(false)
    expect(symbol.LT(10, 12)).to.equal(true)
    expect(symbol.LT()).to.equal(error.na)
    expect(symbol.LT(undefined, undefined)).to.equal(false)
    expect(symbol.LT(1, undefined)).to.equal(false)
    expect(symbol.LT(0, undefined)).to.equal(false)
    expect(symbol.LT(-1, undefined)).to.equal(true)
    expect(symbol.LT(error.na)).to.equal(error.na)
    expect(symbol.LT(1, 'string')).to.equal(true)
    expect(symbol.LT('string', 2)).to.equal(false)
    expect(symbol.LT('a', 'a')).to.equal(false)
    expect(symbol.LT('a', 'ab')).to.equal(true)
    expect(symbol.LT('ab', 'a')).to.equal(false)
  })

  it('LTE', () => {
    expect(symbol.LTE(10, 4)).to.equal(false)
    expect(symbol.LTE(10, 10)).to.equal(true)
    expect(symbol.LTE(10, 12)).to.equal(true)
    expect(symbol.LTE()).to.equal(error.na)
    expect(symbol.LTE(undefined, undefined)).to.equal(true)
    expect(symbol.LTE(1, undefined)).to.equal(false)
    expect(symbol.LTE(0, undefined)).to.equal(true)
    expect(symbol.LTE(-1, undefined)).to.equal(true)
    expect(symbol.LTE(error.na)).to.equal(error.na)
    expect(symbol.LTE(1, 'string')).to.equal(true)
    expect(symbol.LTE('string', 2)).to.equal(false)
    expect(symbol.LTE('a', 'a')).to.equal(true)
    expect(symbol.LTE('a', 'ab')).to.equal(true)
    expect(symbol.LTE('ab', 'a')).to.equal(false)
  })

  it('MINUS', () => {
    expect(symbol.MINUS(10, 4)).to.equal(6)
    expect(symbol.MINUS(1.2, 4)).to.equal(-2.8)
    expect(symbol.MINUS(1, 'string')).to.equal(error.value)
    expect(symbol.MINUS()).to.equal(error.na)
    expect(symbol.MINUS(undefined, undefined)).to.equal(0)
    expect(symbol.MINUS(1, undefined)).to.equal(1)
    expect(symbol.MINUS(undefined, 1)).to.equal(-1)
    expect(symbol.MINUS(null, undefined)).to.equal(0)
    expect(symbol.MINUS(undefined, null)).to.equal(0)
    expect(symbol.MINUS(null, null)).to.equal(0)
    expect(symbol.MINUS(null, 1)).to.equal(-1)
    expect(symbol.MINUS(error.na, undefined)).to.equal(error.na)
    expect(symbol.MINUS(error.na, null)).to.equal(error.na)
    expect(symbol.MINUS(error.na, 1)).to.equal(error.na)
    expect(symbol.MINUS(false, true)).to.equal(-1)
  })

  it('MULTIPLY', () => {
    expect(symbol.MULTIPLY(10, 4)).to.equal(40)
    expect(symbol.MULTIPLY(12, -6)).to.equal(-72)
    expect(symbol.MULTIPLY(0, 0)).to.equal(0)
    expect(symbol.MULTIPLY(1, 0)).to.equal(0)
    expect(symbol.MULTIPLY(0, 1)).to.equal(0)
    expect(symbol.MULTIPLY(1, 'string')).to.equal(error.value)
    expect(symbol.MULTIPLY()).to.equal(error.na)
    expect(symbol.MULTIPLY(undefined, undefined)).to.equal(0)
    expect(symbol.MULTIPLY(1, undefined)).to.equal(0)
    expect(symbol.MULTIPLY(undefined, 1)).to.equal(0)
    expect(symbol.MULTIPLY(null, undefined)).to.equal(0)
    expect(symbol.MULTIPLY(undefined, null)).to.equal(0)
    expect(symbol.MULTIPLY(null, null)).to.equal(0)
    expect(symbol.MULTIPLY(null, 1)).to.equal(0)
    expect(symbol.MULTIPLY(error.na, undefined)).to.equal(error.na)
    expect(symbol.MULTIPLY(error.na, null)).to.equal(error.na)
    expect(symbol.MULTIPLY(error.na, 1)).to.equal(error.na)
    expect(symbol.MULTIPLY(true, false)).to.equal(0)
  })

  it('NE', () => {
    expect(symbol.NE(10, 10)).to.equal(false)
    expect(symbol.NE(1.2, 1.2)).to.equal(false)
    expect(symbol.NE('hello', 'jim')).to.equal(true)
    expect(symbol.NE('hello', 'hello')).to.equal(false)
    expect(symbol.NE(123, 'hello')).to.equal(true)
    expect(symbol.NE(true, true)).to.equal(false)
    expect(symbol.NE(false, false)).to.equal(false)
    expect(symbol.NE(false, 0)).to.equal(true)
    expect(symbol.NE()).to.equal(error.na)
    expect(symbol.NE(undefined, undefined)).to.equal(false)
    expect(symbol.NE(null, null)).to.equal(false)
    expect(symbol.NE(undefined, null)).to.equal(false)
    expect(symbol.NE(error.na)).to.equal(error.na)
    expect(symbol.NE(1, undefined)).to.equal(true)
    expect(symbol.NE(1, 'string')).to.equal(true)
  })

  it('POW', () => {
    expect(symbol.POW(undefined, undefined)).to.equal(error.num)
    expect(symbol.POW(undefined, 2)).to.equal(0)
    expect(symbol.POW(5, undefined)).to.equal(1)
    expect(symbol.POW(error.na, 2)).to.equal(error.na)
    expect(symbol.POW(5, error.na)).to.equal(error.na)
    expect(symbol.POW(5)).to.equal(error.na)
    expect(symbol.POW(5, 2)).to.equal(25)
    expect(symbol.POW(98.6, 3.2)).to.approximately(2401077.2220695773, 1e-9)
    expect(symbol.POW(4, 5 / 4)).to.approximately(5.656854249492381, 1e-9)
    expect(symbol.POW(-1, 0.5)).to.equal(error.num)
    expect(symbol.POW(-1, 'invalid')).to.equal(error.value)
  })
})
